<?php

namespace app\model;

use mon\orm\Model;
use mon\env\Config;
use mon\util\Instance;
use mon\console\Input;
use mon\util\Container;

/**
 * 管理员操作日志模型
 *
 * Class AdminLog
 * @copyright 2021-03-24 mon-console
 * @version 1.0.0
 */
class AdminLogModel extends Model
{
    use Instance;

    /**
     * 操作表
     *
     * @var string
     */
    protected $table = 'admin_log';

    /**
     * 新增自动完成
     *
     * @var array
     */
    protected $insert = ['uid', 'method', 'path', 'ip', 'create_time'];

    /**
     * 运行方式是否为cli
     *
     * @var boolean
     */
    protected $cli;

    /**
     * 用户ID对应的session索引
     *
     * @var string
     */
    protected $session_userid_key;

    /**
     * 构造方法
     */
    public function __construct()
    {
        // 设置默认获取session中的用户ID的索引
        $this->session_userid_key = Config::instance()->get('admin.admin_session_key') . '.id';
        // 运行方式是否为cli
        $this->cli = substr(php_sapi_name(), 0, 3) == 'cli';
    }

    /**
     * 记录日志
     *
     * @param array $option     请求参数
     * @param boolean $logid    是否返回日志ID
     * @return boolean|integer
     */
    public function record(array $option, $logid = false)
    {
        $check = $this->validate()->rule([
            'uid'       => ['int', 'min:0'],
            'method'    => ['str'],
            'path'      => ['str'],
            'action'    => ['required', 'str'],
            'content'   => ['str'],
        ])->message([
            'uid'       => '请输入用户ID',
            'method'    => '请输入合法的请求方式',
            'path'      => '请输入合法的请求路径',
            'action'    => '请输入操作类型',
            'content'   => '请输入操作内容',
        ])->data($option)->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }

        $info = [];
        $info['action'] = $option['action'];
        if (isset($option['uid'])) {
            $info['uid'] = $option['uid'];
        }
        if (isset($option['method']) && !empty($option['method'])) {
            $info['method'] = $option['method'];
        }
        if (isset($option['path']) && !empty($option['path'])) {
            $info['path'] = $option['path'];
        }
        if (isset($option['content']) && !empty($option['content'])) {
            $info['content'] = $option['content'];
        }

        $saveLogID = $this->save($info, null, 'id');
        if (!$saveLogID) {
            $this->error = '记录操作日志失败';
            return false;
        }

        return $logid ? $saveLogID : true;
    }

    /**
     * 查询日志列表
     *
     * @param array $option 请求参数
     * @return array
     */
    public function queryList(array $option)
    {
        $limit = isset($option['limit']) ? intval($option['limit']) : 10;
        $page = isset($option['page']) && is_numeric($option['page']) ? intval($option['page']) : 1;

        // 查询
        $list = $this->scope('list', $option)->page($page, $limit)->order('id', 'DESC')->select();
        $total = $this->scope('list', $option)->count();

        return [
            'list'      => $list,
            'total'     => $total,
            'pageSize'  => $limit,
            'page'      => $page
        ];
    }

    /**
     * 查询列表场景
     *
     * @param [type] $query
     * @param [type] $args
     * @return AdminLogModel
     */
    protected function scopeList($query, $args)
    {
        $field = ['log.*', 'user.username'];
        $query->alias('log')->join(AdminModel::instance()->getTable() . ' user', 'log.uid=user.id', 'left')->field($field);
        // 按用户名
        if (isset($args['username']) && is_string($args['username']) && !empty($args['username'])) {
            $query->whereLike('user.username', trim($args['username']));
        }
        // 时间搜索
        if (isset($args['start_time']) && is_numeric($args['start_time']) && is_int($args['start_time'] + 0) && $args['start_time'] != '') {
            $query->where('log.create_time', '>=', intval($args['start_time']));
        }
        if (isset($args['end_time']) && is_numeric($args['end_time']) && is_int($args['end_time'] + 0) && $args['end_time'] != '') {
            $query->where('log.create_time', '<=', intval($args['end_time']));
        }

        return $query;
    }

    /**
     * 新增时自动写入uid字段
     *
     * @return string
     */
    protected function setUidAttr($val)
    {
        // 未设置uid值，则获取当前请求方式
        return (!$val && $val !== 0) ? ($this->cli ? 0 : Container::instance()->session->get($this->session_userid_key)) : $val;
    }

    /**
     * 新增时自动写入methods字段
     *
     * @return string
     */
    protected function setMethodAttr($val)
    {
        // 未设置method值，则获取当前请求方式
        return !$val ? ($this->cli ? 'cli' : Container::instance()->request->method()) : $val;
    }

    /**
     * 新增时自动写入path字段
     *
     * @return string
     */
    protected function setPathAttr($val)
    {
        // 未设置path值，则获取当前请求方式
        return !$val ? ($this->cli ? Input::instance()->getCommand() : Container::instance()->request->pathInfo()) : $val;
    }

    /**
     * 新增时自动写入ip字段
     *
     * @return string
     */
    protected function setIpAttr()
    {
        return $this->cli ? '0.0.0.0' : Container::instance()->request->ip();
    }

    /**
     * 自动完成create_time字段
     * 
     * @param mixed $val 默认值
     * @param array  $row 列值
     * @return string
     */
    protected function setCreateTimeAttr($val)
    {
        return time();
    }
}
